<template>
	<view class="canvas-wrapper">
		<canvas canvas-id="normalCanvas" id="normalCanvas" class="normal-probability-canvas"></canvas>
	</view>
</template>

<script>
	export default {
		props: {
			data: {
				type: Array,
				required: true
			}
		},
		mounted() {
			this.drawCanvas();
		},
		methods: {
			quantileNormal(p) {
				if (p <= 0) return -Infinity;
				if (p >= 1) return Infinity;
				if (p < 0.5) return -this.quantileNormal(1 - p);

				const t = Math.sqrt(-2.0 * Math.log(1 - p));
				const c0 = 2.515517;
				const c1 = 0.802853;
				const c2 = 0.010328;
				const d1 = 1.432788;
				const d2 = 0.189269;
				const d3 = 0.001308;

				return t - ((c0 + c1 * t + c2 * t * t) / (1 + d1 * t + d2 * t * t + d3 * t * t * t));
			},

			calculateMean(data) {
				return data.reduce((sum, val) => sum + val, 0) / data.length;
			},

			calculateStdDev(data, mean) {
				const variance = data.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / data.length;
				return Math.sqrt(variance);
			},

			drawCanvas() {
				const allSamples = this.data.flatMap(item => item.samples);
				const sorted = allSamples.slice().sort((a, b) => a - b);
				const n = sorted.length;
				if (n <= 1) return;

				const mean = this.calculateMean(sorted);
				const stdDev = this.calculateStdDev(sorted, mean);

				const points = sorted.map((val, i) => {
					const p = (i + 0.5) / n;
					const z = this.quantileNormal(p);
					return [val, z];
				});

				const realMin = sorted[0];
				const realMax = sorted[n - 1];
				const range = realMax - realMin;
				const xMin = range > 0 ? realMin - range * 0.05 : realMin - 0.5;
				const xMax = range > 0 ? realMax + range * 0.05 : realMax + 0.5;

				const zMin = this.quantileNormal(0.005);
				const zMax = this.quantileNormal(0.996);

				const query = uni.createSelectorQuery().in(this);
				query.select('#normalCanvas').boundingClientRect(res => {
					const W = res.width;
					const H = res.height;
					const padding = 40;
					const ctx = uni.createCanvasContext('normalCanvas', this);

					const mapX = x => padding + ((x - xMin) / (xMax - xMin)) * (W - 2 * padding);
					const mapY = z => H - padding - ((z - zMin) / (zMax - zMin)) * (H - 2 * padding);

					// 清空背景
					ctx.setFillStyle('#fff');
					ctx.fillRect(0, 0, W, H);

					// 1. 绘制网格线（虚线）
					ctx.setStrokeStyle('#eee');
					ctx.setLineWidth(1);
					ctx.setLineDash([4, 4]);

					// 生成均匀分布的X轴刻度（增加到15个）
					const tickCount = 15;  // 修改为15个刻度点
					const xTicks = [];
					for (let i = 0; i < tickCount; i++) {
						xTicks.push(xMin + (xMax - xMin) * i / (tickCount - 1));
					}

					// 绘制X轴网格线（均匀分布）
					xTicks.forEach(val => {
						const x = mapX(val);
						ctx.beginPath();
						ctx.moveTo(x, padding);
						ctx.lineTo(x, H - padding);
						ctx.stroke();
					});

					// Y轴网格线（保持不变）
					const yTicks = [1, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99];
					ctx.setFontSize(10);
					ctx.setFillStyle('#333');

					yTicks.forEach(percent => {
						const p = percent / 100;
						const z = this.quantileNormal(p);
						const y = mapY(z);

						// 网格线
						ctx.beginPath();
						ctx.moveTo(padding, y);
						ctx.lineTo(W - padding, y);
						ctx.stroke();

						// 坐标刻度线
						const tickLength = 8;
						ctx.beginPath();
						ctx.moveTo(padding - tickLength, y);
						ctx.lineTo(padding, y);
						ctx.stroke();

						// 文字
						ctx.fillText(percent, 5, y + 3);
					});

					// 2. 绘制 X 轴刻度和文本（均匀分布）
					ctx.setFontSize(9);  // 稍微减小字体大小以适应更多刻度
					ctx.setFillStyle('#333');
					ctx.setLineDash([]); // 恢复实线

					// 使用均匀分布的刻度
					xTicks.forEach(val => {
						const x = mapX(val);
						// 刻度线
						ctx.beginPath();
						ctx.moveTo(x, H - padding);
						ctx.lineTo(x, H - padding + 6);
						ctx.stroke();

						// 刻度标签（水平居中）
						ctx.save();
						ctx.textAlign = 'center';
						// 根据数值范围决定显示精度
						const precision = (xMax - xMin) > 10 ? 1 : 2;
						ctx.fillText(val.toFixed(precision), x, H - padding + 18);
						ctx.restore();
					});

					// 3. 绘制坐标轴线（实线）
					ctx.setStrokeStyle('#333');
					ctx.setLineWidth(2);
					ctx.setLineDash([]);

					// Y轴
					ctx.beginPath();
					ctx.moveTo(padding, padding);
					ctx.lineTo(padding, H - padding);
					ctx.stroke();

					// X轴
					ctx.beginPath();
					ctx.moveTo(padding, H - padding);
					ctx.lineTo(W - padding, H - padding);
					ctx.stroke();

					// 4. 绘制红色样本点
					ctx.setFillStyle('#FF0000');
					points.forEach(([val, z]) => {
						const x = mapX(val);
						const y = mapY(z);
						ctx.beginPath();
						ctx.arc(x, y, 3, 0, Math.PI * 2);
						ctx.fill();
					});

					// 5. 绘制蓝色理论线
					ctx.setStrokeStyle('#3a73f1');
					ctx.setLineWidth(1);
					ctx.beginPath();
					ctx.moveTo(mapX(xMin), mapY((xMin - mean) / stdDev));
					ctx.lineTo(mapX(xMax), mapY((xMax - mean) / stdDev));
					ctx.stroke();

					ctx.draw();
				}).exec();
			}
		}
	};
</script>

<style scoped>
	.canvas-wrapper {
		width: 100%;
		height: 400px;
		position: relative;
	}

	.normal-probability-canvas {
		width: 100%;
		height: 100%;
		background-color: #fff;
	}
</style>